package com.dtp.core.spring;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.RunnableFuture;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * DtpLifecycleSupport主要实现Spring bean的生命周期方法，模仿Spring内部线程池ThreadPoolTaskExecutor
 *
 * @author yanhom
 * @since 1.0.3
 *
 * @remark muse
 **/
@Slf4j
public abstract class DtpLifecycleSupport extends ThreadPoolExecutor implements InitializingBean, DisposableBean {
    protected String threadPoolName; // 唯一标识
    protected boolean waitForTasksToCompleteOnShutdown = false; // 是否在关闭时等待定时任务完成，不中断正在运行的任务并执行队列中的所有任务
    protected int awaitTerminationSeconds = 0; // 为了在容器的其他部分继续关闭之前等待剩余的任务完成执行，该执行器在关闭时应该阻塞的最大秒数

    public DtpLifecycleSupport(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit,
                               BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory,
                               RejectedExecutionHandler handler) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);
    }

    /** 初始化操作，该方法具体是由DtpExecutor来实现的 */
    @Override
    public void afterPropertiesSet() {initialize();}

    /** 当Spring初始化调用afterPropertiesSet()方法时，则会调用该方法 */
    protected abstract void initialize();

    /** 当BeanFactory销毁任务执行器实例的时候，会请求destroy方法 */
    @Override
    public void destroy() {internalShutdown();}

    /** 在底层的ExecutorService上执行关闭 */
    public void internalShutdown() {
        if (this.waitForTasksToCompleteOnShutdown)
            this.shutdown(); // 执行线程池关闭操作
        else
            for (Runnable remainingTask : this.shutdownNow()) cancelRemainingTask(remainingTask); // 执行任务取消操作
        awaitTerminationIfNecessary(); // 等待执行器终止
    }

    /** 取消从ExecutorService#shutdownNow()方法返回的从未推荐执行的给定剩余任务 */
    protected void cancelRemainingTask(Runnable task) {
        if (task instanceof Future) ((Future<?>) task).cancel(true);
    }

    /** 等待执行器终止，根据值“awaitTerminationSeconds”属性判断 */
    private void awaitTerminationIfNecessary() {
        if (this.awaitTerminationSeconds <= 0) return;

        try {
            if (!awaitTermination(this.awaitTerminationSeconds, TimeUnit.SECONDS) && log.isWarnEnabled())
                log.warn("Timed out while waiting for executor {} to terminate", threadPoolName);
        } catch (InterruptedException ex) {
            if (log.isWarnEnabled())
                log.warn("Interrupted while waiting for executor {} to terminate", threadPoolName);
            Thread.currentThread().interrupt();
        }
    }

    public void setWaitForTasksToCompleteOnShutdown(boolean waitForTasksToCompleteOnShutdown) {
        this.waitForTasksToCompleteOnShutdown = waitForTasksToCompleteOnShutdown;
    }
    public void setAwaitTerminationSeconds(int awaitTerminationSeconds) {
        this.awaitTerminationSeconds = awaitTerminationSeconds;
    }
    public void setThreadPoolName(String threadPoolName) {
        this.threadPoolName = threadPoolName;
    }
    public String getThreadPoolName() {
        return threadPoolName;
    }
}
